﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

using Opentao.NotificationService.Common.Data.Entities;

namespace Opentao.NotificationService.Business.Objects
{
    public abstract class EntityBaseBO : IDisposable
    {
        protected readonly NSDbModelContainer Context = new NSDbModelContainer();




        #region Protected Methods
        protected void CreateRecords< T >( List<T> records ) where T : EntityBase
        {
            records.ForEach( r => Context.Set<T>().Add( r ) );
            Context.SaveChanges();
        }

        protected IQueryable<T> GetRecords< T >( List<int> ids ) where T : EntityBase
        {
            return Context.Set<T>().Where( r => ids.Any( id => id == r.Id ) );
        }

        protected void UpdateRecords< T >( List<T> records ) where T : EntityBase
        {
            foreach( var record in records ) {
                Context.Set<T>().Add( record );
                Context.Entry( record ).State = EntityState.Modified;
                Context.SaveChanges();
            }
        }

        protected void DeleteRecords< T >( List<T> records ) where T : EntityBase
        {
            records.ForEach( r => Context.Set<T>().Remove( r ) );
            Context.SaveChanges();
        }

        protected List<T> AttachRecordsToContext< T >( List<int> ids ) where T : EntityBase, new()
        {
            return ids.Select(
                id => Context.Set<T>().Attach(
                    new T {
                              Id = id
                          } ) ).ToList();
        }

        // TODO: Было бы здорово обобщить ещё и сортировку.
        protected IQueryable<T> PaginateQuery< T >(
            IQueryable<T> query,
            int recordsPerPage,
            int pageNumber ) where T : EntityBase
        {
            return recordsPerPage < 1
                       ? query
                       : query.Skip( CalculateRecordsToSkip( recordsPerPage, pageNumber ) ).Take( recordsPerPage );
        }
        #endregion




        #region Private Methods
        private static int CalculateRecordsToSkip(
            int recordsPerPage,
            int pageNumber )
        {
            return pageNumber*recordsPerPage;
        }
        #endregion




        #region Implementation of IDisposable
        /// <summary>
        /// Закрыть установленное соединение.
        /// </summary>
        public void Dispose()
        {
            Context.Dispose();
        }
        #endregion
    }
}